"""
时间处理工具模块

提供时间字段检测、格式解析、时区处理等功能。
"""

import re
import pytz
from datetime import datetime, timezone, timedelta
from typing import Dict, List, Optional, Any, Tuple, Union
from ..utils.logger import get_module_logger
from ..utils.exceptions import TimeFieldError, TimeFormatError, ErrorCode

logger = get_module_logger(__name__)


class TimeFieldDetector:
    """时间字段检测器
    
    自动检测ES索引中的时间字段，支持嵌套字段和字段评分。
    """
    
    def __init__(self, candidates: Optional[List[str]] = None):
        """初始化时间字段检测器
        
        Args:
            candidates: 时间字段候选列表
        """
        self.candidates = candidates or [
            "@timestamp", "timestamp", "created_at", "updated_at", 
            "event_time", "log_time", "time", "date", "datetime",
            "event.timestamp", "log.timestamp", "message.timestamp"
        ]
        
        # 时间字段名称模式
        self.time_patterns = [
            r'.*timestamp.*',
            r'.*time.*',
            r'.*date.*',
            r'.*created.*',
            r'.*updated.*',
            r'.*modified.*',
            r'.*occurred.*',
            r'.*event.*time.*',
            r'.*log.*time.*'
        ]
        
        # 编译正则表达式
        self.compiled_patterns = [re.compile(pattern, re.IGNORECASE) for pattern in self.time_patterns]
    
    def detect_time_fields(self, mapping: Dict[str, Any]) -> List[Tuple[str, float]]:
        """检测索引映射中的时间字段
        
        Args:
            mapping: ES索引映射
            
        Returns:
            时间字段列表，每个元素为(字段路径, 评分)的元组，按评分降序排列
        """
        logger.debug("开始检测时间字段")
        
        time_fields = []
        flattened_mapping = self._flatten_mapping(mapping)
        
        for field_path, field_info in flattened_mapping.items():
            if self._is_time_field(field_path, field_info):
                score = self._calculate_field_score(field_path, field_info)
                time_fields.append((field_path, score))
                logger.debug(f"发现时间字段: {field_path}, 评分: {score:.2f}")
        
        # 按评分降序排列
        time_fields.sort(key=lambda x: x[1], reverse=True)
        
        logger.info(f"检测到 {len(time_fields)} 个时间字段")
        return time_fields
    
    def _flatten_mapping(self, mapping: Dict[str, Any], prefix: str = "") -> Dict[str, Dict[str, Any]]:
        """展平嵌套的映射结构
        
        Args:
            mapping: 映射字典
            prefix: 字段路径前缀
            
        Returns:
            展平后的映射字典
        """
        flattened = {}
        
        for key, value in mapping.items():
            if key in ['mappings', 'properties']:
                # 跳过顶层的mappings和properties键
                flattened.update(self._flatten_mapping(value, prefix))
                continue
            
            current_path = f"{prefix}.{key}" if prefix else key
            
            if isinstance(value, dict):
                if 'type' in value:
                    # 这是一个字段定义
                    flattened[current_path] = value
                elif 'properties' in value:
                    # 这是一个对象类型，继续展平其属性
                    flattened.update(self._flatten_mapping(value['properties'], current_path))
                else:
                    # 其他嵌套结构
                    flattened.update(self._flatten_mapping(value, current_path))
        
        return flattened
    
    def _is_time_field(self, field_path: str, field_info: Dict[str, Any]) -> bool:
        """判断字段是否为时间字段
        
        Args:
            field_path: 字段路径
            field_info: 字段信息
            
        Returns:
            是否为时间字段
        """
        # 检查字段类型
        field_type = field_info.get('type', '').lower()
        if field_type in ['date', 'date_nanos']:
            return True
        
        # 检查字段名称模式
        for pattern in self.compiled_patterns:
            if pattern.match(field_path):
                return True
        
        return False
    
    def _calculate_field_score(self, field_path: str, field_info: Dict[str, Any]) -> float:
        """计算时间字段的评分
        
        Args:
            field_path: 字段路径
            field_info: 字段信息
            
        Returns:
            字段评分 (0-100)
        """
        score = 0.0
        
        # 基础分数：字段类型
        field_type = field_info.get('type', '').lower()
        if field_type == 'date':
            score += 50.0
        elif field_type == 'date_nanos':
            score += 45.0  # 稍低于date，因为不太常用
        
        # 字段名称评分
        field_name = field_path.lower()
        
        # 精确匹配候选字段
        if field_path in self.candidates:
            candidate_index = self.candidates.index(field_path)
            score += 30.0 - (candidate_index * 2.0)  # 越靠前分数越高
        
        # 常见时间字段名称
        if field_name in ['@timestamp', 'timestamp']:
            score += 25.0
        elif field_name in ['created_at', 'updated_at']:
            score += 20.0
        elif field_name in ['event_time', 'log_time']:
            score += 15.0
        elif 'timestamp' in field_name:
            score += 10.0
        elif 'time' in field_name:
            score += 8.0
        elif 'date' in field_name:
            score += 6.0
        
        # 字段路径深度惩罚
        depth = field_path.count('.')
        score -= depth * 2.0  # 嵌套越深分数越低
        
        # 字段格式信息
        if 'format' in field_info:
            format_str = field_info['format']
            if 'strict_date_optional_time' in format_str:
                score += 5.0
            elif 'epoch_millis' in format_str:
                score += 4.0
            elif 'epoch_second' in format_str:
                score += 3.0
        
        return max(0.0, min(100.0, score))  # 限制在0-100范围内
    
    def validate_time_field(self, field_path: str, mapping: Dict[str, Any]) -> bool:
        """验证时间字段是否有效
        
        Args:
            field_path: 字段路径
            mapping: 索引映射
            
        Returns:
            字段是否有效
            
        Raises:
            TimeFieldError: 字段验证失败
        """
        logger.debug(f"验证时间字段: {field_path}")
        
        flattened_mapping = self._flatten_mapping(mapping)
        
        if field_path not in flattened_mapping:
            raise TimeFieldError(
                f"时间字段不存在: {field_path}",
                field_path,
                ErrorCode.TIME_FIELD_NOT_FOUND
            )
        
        field_info = flattened_mapping[field_path]
        field_type = field_info.get('type', '').lower()
        
        if field_type not in ['date', 'date_nanos']:
            raise TimeFieldError(
                f"字段类型不是时间类型: {field_path} (类型: {field_type})",
                field_path,
                ErrorCode.TIME_FIELD_INVALID
            )
        
        logger.debug(f"时间字段验证通过: {field_path}")
        return True
    
    def get_field_format(self, field_path: str, mapping: Dict[str, Any]) -> Optional[str]:
        """获取时间字段的格式信息
        
        Args:
            field_path: 字段路径
            mapping: 索引映射
            
        Returns:
            字段格式字符串，如果没有则返回None
        """
        flattened_mapping = self._flatten_mapping(mapping)
        
        if field_path not in flattened_mapping:
            return None
        
        field_info = flattened_mapping[field_path]
        return field_info.get('format')
    
    def suggest_time_field(self, mapping: Dict[str, Any]) -> Optional[str]:
        """建议最佳的时间字段
        
        Args:
            mapping: 索引映射
            
        Returns:
            建议的时间字段路径，如果没有找到则返回None
        """
        time_fields = self.detect_time_fields(mapping)
        
        if not time_fields:
            logger.warning("未找到任何时间字段")
            return None
        
        best_field = time_fields[0][0]
        logger.info(f"建议使用时间字段: {best_field}")
        return best_field
    
    def get_time_field_info(self, field_path: str, mapping: Dict[str, Any]) -> Dict[str, Any]:
        """获取时间字段的详细信息
        
        Args:
            field_path: 字段路径
            mapping: 索引映射
            
        Returns:
            字段详细信息
        """
        flattened_mapping = self._flatten_mapping(mapping)
        
        if field_path not in flattened_mapping:
            raise TimeFieldError(
                f"时间字段不存在: {field_path}",
                field_path,
                ErrorCode.TIME_FIELD_NOT_FOUND
            )
        
        field_info = flattened_mapping[field_path]
        score = self._calculate_field_score(field_path, field_info)
        
        return {
            'path': field_path,
            'type': field_info.get('type'),
            'format': field_info.get('format'),
            'score': score,
            'is_valid': self._is_time_field(field_path, field_info),
            'raw_info': field_info
        }


class TimeFieldAnalyzer:
    """时间字段分析器
    
    分析时间字段的数据质量和特征。
    """
    
    def __init__(self, es_client):
        """初始化时间字段分析器
        
        Args:
            es_client: ES客户端
        """
        self.es_client = es_client
        self.detector = TimeFieldDetector()
    
    def analyze_time_field_data(
        self, 
        index: str, 
        time_field: str, 
        sample_size: int = 1000
    ) -> Dict[str, Any]:
        """分析时间字段的数据特征
        
        Args:
            index: 索引名称
            time_field: 时间字段名称
            sample_size: 采样大小
            
        Returns:
            分析结果
        """
        logger.info(f"分析时间字段数据: {index}.{time_field}")
        
        # 获取样本数据
        query = {
            "size": sample_size,
            "_source": [time_field],
            "query": {
                "exists": {
                    "field": time_field
                }
            }
        }
        
        try:
            response = self.es_client.search(index=index, body=query)
            hits = response['hits']['hits']
            
            if not hits:
                return {
                    'total_docs': 0,
                    'sample_size': 0,
                    'has_data': False,
                    'error': '没有找到包含时间字段的文档'
                }
            
            # 分析时间值
            time_values = []
            missing_count = 0
            
            for hit in hits:
                source = hit['_source']
                time_value = self._extract_nested_value(source, time_field)
                
                if time_value is None:
                    missing_count += 1
                else:
                    time_values.append(time_value)
            
            # 统计分析
            analysis = {
                'total_docs': response['hits']['total']['value'],
                'sample_size': len(hits),
                'has_data': len(time_values) > 0,
                'missing_count': missing_count,
                'valid_count': len(time_values),
                'missing_rate': missing_count / len(hits) if hits else 0,
            }
            
            if time_values:
                analysis.update(self._analyze_time_values(time_values))
            
            return analysis
            
        except Exception as e:
            logger.error(f"分析时间字段数据失败: {e}")
            return {
                'error': str(e),
                'has_data': False
            }
    
    def _extract_nested_value(self, source: Dict[str, Any], field_path: str) -> Any:
        """从嵌套字典中提取值
        
        Args:
            source: 源字典
            field_path: 字段路径 (支持点号分隔)
            
        Returns:
            字段值，如果不存在则返回None
        """
        keys = field_path.split('.')
        current = source
        
        for key in keys:
            if isinstance(current, dict) and key in current:
                current = current[key]
            else:
                return None
        
        return current
    
    def _analyze_time_values(self, time_values: List[Any]) -> Dict[str, Any]:
        """分析时间值的特征
        
        Args:
            time_values: 时间值列表
            
        Returns:
            分析结果
        """
        # 格式分析
        format_stats = {}
        parsed_times = []
        
        for value in time_values:
            value_str = str(value)
            format_type = self._detect_time_format(value_str)
            format_stats[format_type] = format_stats.get(format_type, 0) + 1
            
            # 尝试解析时间
            try:
                parsed_time = self._parse_time_value(value)
                if parsed_time:
                    parsed_times.append(parsed_time)
            except:
                pass
        
        analysis = {
            'format_distribution': format_stats,
            'format_consistency': len(format_stats) == 1,
            'dominant_format': max(format_stats.items(), key=lambda x: x[1])[0] if format_stats else None
        }
        
        # 时间范围分析
        if parsed_times:
            parsed_times.sort()
            analysis.update({
                'time_range': {
                    'min': parsed_times[0].isoformat(),
                    'max': parsed_times[-1].isoformat(),
                    'span_days': (parsed_times[-1] - parsed_times[0]).days
                },
                'parsed_count': len(parsed_times),
                'parse_success_rate': len(parsed_times) / len(time_values)
            })
        
        return analysis
    
    def _detect_time_format(self, value_str: str) -> str:
        """检测时间格式类型
        
        Args:
            value_str: 时间值字符串
            
        Returns:
            格式类型
        """
        # ISO 8601 格式
        if re.match(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}', value_str):
            return 'iso_8601'
        
        # Unix 时间戳 (毫秒)
        if re.match(r'^\d{13}$', value_str):
            return 'epoch_millis'
        
        # Unix 时间戳 (秒)
        if re.match(r'^\d{10}$', value_str):
            return 'epoch_second'
        
        # 日期格式
        if re.match(r'\d{4}-\d{2}-\d{2}', value_str):
            return 'date_only'
        
        # 其他格式
        return 'custom'
    
    def _parse_time_value(self, value: Any) -> Optional[datetime]:
        """解析时间值
        
        Args:
            value: 时间值
            
        Returns:
            解析后的datetime对象，失败返回None
        """
        if isinstance(value, datetime):
            return value
        
        value_str = str(value).strip()
        
        # 尝试不同的解析方法
        parsers = [
            self._parse_iso_format,
            self._parse_epoch_millis,
            self._parse_epoch_second,
            self._parse_common_formats
        ]
        
        for parser in parsers:
            try:
                result = parser(value_str)
                if result:
                    return result
            except:
                continue
        
        return None
    
    def _parse_iso_format(self, value_str: str) -> Optional[datetime]:
        """解析ISO格式时间"""
        try:
            return datetime.fromisoformat(value_str.replace('Z', '+00:00'))
        except:
            return None
    
    def _parse_epoch_millis(self, value_str: str) -> Optional[datetime]:
        """解析毫秒时间戳"""
        try:
            if len(value_str) == 13 and value_str.isdigit():
                timestamp = int(value_str) / 1000
                return datetime.fromtimestamp(timestamp, tz=timezone.utc)
        except:
            pass
        return None
    
    def _parse_epoch_second(self, value_str: str) -> Optional[datetime]:
        """解析秒时间戳"""
        try:
            if len(value_str) == 10 and value_str.isdigit():
                timestamp = int(value_str)
                return datetime.fromtimestamp(timestamp, tz=timezone.utc)
        except:
            pass
        return None
    
    def _parse_common_formats(self, value_str: str) -> Optional[datetime]:
        """解析常见时间格式"""
        formats = [
            '%Y-%m-%d %H:%M:%S',
            '%Y/%m/%d %H:%M:%S',
            '%Y-%m-%d',
            '%Y/%m/%d',
            '%d/%m/%Y %H:%M:%S',
            '%d-%m-%Y %H:%M:%S'
        ]
        
        for fmt in formats:
            try:
                return datetime.strptime(value_str, fmt)
            except:
                continue
        
        return None


class TimeFormatParser:
    """时间格式解析器

    支持多种时间格式的解析和转换。
    """

    def __init__(self):
        """初始化时间格式解析器"""
        # 支持的时间格式模式
        self.format_patterns = [
            # ISO 8601 格式
            (r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,6})?Z?$', 'iso_8601'),
            (r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,6})?[+-]\d{2}:\d{2}$', 'iso_8601_tz'),

            # Unix 时间戳
            (r'^\d{13}$', 'epoch_millis'),
            (r'^\d{10}$', 'epoch_second'),
            (r'^\d{16}$', 'epoch_micros'),

            # 常见日期时间格式
            (r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', 'datetime_hyphen'),
            (r'^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}$', 'datetime_slash'),
            (r'^\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}$', 'datetime_us'),
            (r'^\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}$', 'datetime_eu'),

            # 日期格式
            (r'^\d{4}-\d{2}-\d{2}$', 'date_iso'),
            (r'^\d{4}/\d{2}/\d{2}$', 'date_slash'),
            (r'^\d{2}/\d{2}/\d{4}$', 'date_us'),
            (r'^\d{2}-\d{2}-\d{4}$', 'date_eu'),
        ]

        # 编译正则表达式
        self.compiled_patterns = [(re.compile(pattern), format_type)
                                 for pattern, format_type in self.format_patterns]

        # 格式解析函数映射
        self.parsers = {
            'iso_8601': self._parse_iso_8601,
            'iso_8601_tz': self._parse_iso_8601_tz,
            'epoch_millis': self._parse_epoch_millis,
            'epoch_second': self._parse_epoch_second,
            'epoch_micros': self._parse_epoch_micros,
            'datetime_hyphen': self._parse_datetime_hyphen,
            'datetime_slash': self._parse_datetime_slash,
            'datetime_us': self._parse_datetime_us,
            'datetime_eu': self._parse_datetime_eu,
            'date_iso': self._parse_date_iso,
            'date_slash': self._parse_date_slash,
            'date_us': self._parse_date_us,
            'date_eu': self._parse_date_eu,
        }

    def detect_format(self, time_str: str) -> Optional[str]:
        """检测时间字符串的格式

        Args:
            time_str: 时间字符串

        Returns:
            格式类型，如果无法识别则返回None
        """
        time_str = str(time_str).strip()

        for pattern, format_type in self.compiled_patterns:
            if pattern.match(time_str):
                return format_type

        return None

    def parse_time(self, time_str: str, format_hint: Optional[str] = None) -> Optional[datetime]:
        """解析时间字符串

        Args:
            time_str: 时间字符串
            format_hint: 格式提示

        Returns:
            解析后的datetime对象，失败返回None
        """
        time_str = str(time_str).strip()

        # 如果提供了格式提示，优先使用
        if format_hint and format_hint in self.parsers:
            try:
                return self.parsers[format_hint](time_str)
            except Exception as e:
                logger.debug(f"使用格式提示 {format_hint} 解析失败: {e}")

        # 自动检测格式
        detected_format = self.detect_format(time_str)
        if detected_format and detected_format in self.parsers:
            try:
                return self.parsers[detected_format](time_str)
            except Exception as e:
                logger.debug(f"使用检测格式 {detected_format} 解析失败: {e}")

        # 尝试所有解析器
        for format_type, parser in self.parsers.items():
            try:
                result = parser(time_str)
                if result:
                    logger.debug(f"使用格式 {format_type} 成功解析时间")
                    return result
            except:
                continue

        logger.warning(f"无法解析时间字符串: {time_str}")
        return None

    def _parse_iso_8601(self, time_str: str) -> datetime:
        """解析ISO 8601格式"""
        # 处理Z后缀
        if time_str.endswith('Z'):
            time_str = time_str[:-1] + '+00:00'

        return datetime.fromisoformat(time_str)

    def _parse_iso_8601_tz(self, time_str: str) -> datetime:
        """解析带时区的ISO 8601格式"""
        return datetime.fromisoformat(time_str)

    def _parse_epoch_millis(self, time_str: str) -> datetime:
        """解析毫秒时间戳"""
        timestamp = int(time_str) / 1000
        return datetime.fromtimestamp(timestamp, tz=timezone.utc)

    def _parse_epoch_second(self, time_str: str) -> datetime:
        """解析秒时间戳"""
        timestamp = int(time_str)
        return datetime.fromtimestamp(timestamp, tz=timezone.utc)

    def _parse_epoch_micros(self, time_str: str) -> datetime:
        """解析微秒时间戳"""
        timestamp = int(time_str) / 1000000
        return datetime.fromtimestamp(timestamp, tz=timezone.utc)

    def _parse_datetime_hyphen(self, time_str: str) -> datetime:
        """解析 YYYY-MM-DD HH:MM:SS 格式"""
        return datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')

    def _parse_datetime_slash(self, time_str: str) -> datetime:
        """解析 YYYY/MM/DD HH:MM:SS 格式"""
        return datetime.strptime(time_str, '%Y/%m/%d %H:%M:%S')

    def _parse_datetime_us(self, time_str: str) -> datetime:
        """解析美式 MM/DD/YYYY HH:MM:SS 格式"""
        return datetime.strptime(time_str, '%m/%d/%Y %H:%M:%S')

    def _parse_datetime_eu(self, time_str: str) -> datetime:
        """解析欧式 DD-MM-YYYY HH:MM:SS 格式"""
        return datetime.strptime(time_str, '%d-%m-%Y %H:%M:%S')

    def _parse_date_iso(self, time_str: str) -> datetime:
        """解析 YYYY-MM-DD 格式"""
        return datetime.strptime(time_str, '%Y-%m-%d')

    def _parse_date_slash(self, time_str: str) -> datetime:
        """解析 YYYY/MM/DD 格式"""
        return datetime.strptime(time_str, '%Y/%m/%d')

    def _parse_date_us(self, time_str: str) -> datetime:
        """解析美式 MM/DD/YYYY 格式"""
        return datetime.strptime(time_str, '%m/%d/%Y')

    def _parse_date_eu(self, time_str: str) -> datetime:
        """解析欧式 DD-MM-YYYY 格式"""
        return datetime.strptime(time_str, '%d-%m-%Y')

    def format_time(self, dt: datetime, target_format: str = 'iso_8601') -> str:
        """格式化时间为指定格式

        Args:
            dt: datetime对象
            target_format: 目标格式

        Returns:
            格式化后的时间字符串
        """
        formatters = {
            'iso_8601': lambda d: d.isoformat(),
            'epoch_millis': lambda d: str(int(d.timestamp() * 1000)),
            'epoch_second': lambda d: str(int(d.timestamp())),
            'datetime_hyphen': lambda d: d.strftime('%Y-%m-%d %H:%M:%S'),
            'datetime_slash': lambda d: d.strftime('%Y/%m/%d %H:%M:%S'),
            'date_iso': lambda d: d.strftime('%Y-%m-%d'),
        }

        formatter = formatters.get(target_format)
        if formatter:
            return formatter(dt)
        else:
            return dt.isoformat()  # 默认使用ISO格式

    def convert_format(self, time_str: str, target_format: str, source_format: Optional[str] = None) -> Optional[str]:
        """转换时间格式

        Args:
            time_str: 源时间字符串
            target_format: 目标格式
            source_format: 源格式提示

        Returns:
            转换后的时间字符串，失败返回None
        """
        # 解析源时间
        dt = self.parse_time(time_str, source_format)
        if dt is None:
            return None

        # 格式化为目标格式
        return self.format_time(dt, target_format)

    def validate_format(self, time_str: str, expected_format: str) -> bool:
        """验证时间字符串是否符合指定格式

        Args:
            time_str: 时间字符串
            expected_format: 期望的格式

        Returns:
            是否符合格式
        """
        detected_format = self.detect_format(time_str)
        return detected_format == expected_format

    def get_supported_formats(self) -> List[str]:
        """获取支持的格式列表

        Returns:
            支持的格式列表
        """
        return list(self.parsers.keys())

    def analyze_time_strings(self, time_strings: List[str]) -> Dict[str, Any]:
        """分析时间字符串列表的格式分布

        Args:
            time_strings: 时间字符串列表

        Returns:
            分析结果
        """
        format_counts = {}
        parse_success = 0
        parse_failures = []

        for time_str in time_strings:
            detected_format = self.detect_format(time_str)
            if detected_format:
                format_counts[detected_format] = format_counts.get(detected_format, 0) + 1
                if self.parse_time(time_str):
                    parse_success += 1
                else:
                    parse_failures.append(time_str)
            else:
                format_counts['unknown'] = format_counts.get('unknown', 0) + 1
                parse_failures.append(time_str)

        total_count = len(time_strings)

        return {
            'total_count': total_count,
            'format_distribution': format_counts,
            'parse_success_count': parse_success,
            'parse_success_rate': parse_success / total_count if total_count > 0 else 0,
            'parse_failures': parse_failures[:10],  # 只返回前10个失败案例
            'dominant_format': max(format_counts.items(), key=lambda x: x[1])[0] if format_counts else None,
            'format_consistency': len([f for f in format_counts.keys() if f != 'unknown']) == 1
        }


class TimezoneHandler:
    """时区处理器

    处理时区检测、转换、夏令时等复杂时区问题。
    """

    def __init__(self):
        """初始化时区处理器"""
        # 常见时区映射
        self.timezone_mapping = {
            'CST': 'Asia/Shanghai',
            'EST': 'America/New_York',
            'PST': 'America/Los_Angeles',
            'GMT': 'GMT',
            'UTC': 'UTC',
            'JST': 'Asia/Tokyo',
            'KST': 'Asia/Seoul',
            'IST': 'Asia/Kolkata',
            'CET': 'Europe/Berlin',
            'MST': 'America/Denver',
        }

        # 时区检测模式
        self.timezone_patterns = [
            (r'[+-]\d{2}:\d{2}$', 'offset'),
            (r'[+-]\d{4}$', 'offset_compact'),
            (r'Z$', 'utc'),
            (r'\s+(CST|EST|PST|GMT|UTC|JST|KST|IST|CET|MST)$', 'abbreviation'),
        ]

        self.compiled_tz_patterns = [(re.compile(pattern), tz_type)
                                    for pattern, tz_type in self.timezone_patterns]

    def detect_timezone(self, time_str: str) -> Optional[str]:
        """检测时间字符串中的时区信息

        Args:
            time_str: 时间字符串

        Returns:
            检测到的时区名称，如果没有则返回None
        """
        time_str = str(time_str).strip()

        for pattern, tz_type in self.compiled_tz_patterns:
            match = pattern.search(time_str)
            if match:
                if tz_type == 'offset':
                    # 直接返回偏移量
                    return match.group()
                elif tz_type == 'offset_compact':
                    # 转换为标准偏移格式
                    offset = match.group()
                    return f"{offset[:3]}:{offset[3:]}"
                elif tz_type == 'utc':
                    return 'UTC'
                elif tz_type == 'abbreviation':
                    abbr = match.group(1)
                    return self.timezone_mapping.get(abbr, abbr)

        return None

    def normalize_timezone(self, tz_input: Union[str, timezone, None]) -> Optional[timezone]:
        """标准化时区输入

        Args:
            tz_input: 时区输入（字符串、timezone对象或None）

        Returns:
            标准化的timezone对象
        """
        if tz_input is None:
            return None

        if isinstance(tz_input, timezone):
            return tz_input

        tz_str = str(tz_input).strip()

        # 处理特殊值
        if tz_str.lower() in ['auto', 'local']:
            return None  # 需要进一步处理
        elif tz_str.upper() in ['UTC', 'GMT']:
            return timezone.utc

        # 处理偏移量格式
        if re.match(r'^[+-]\d{2}:\d{2}$', tz_str):
            return self._parse_offset_timezone(tz_str)

        # 处理时区名称
        try:
            return pytz.timezone(tz_str)
        except pytz.UnknownTimeZoneError:
            # 尝试映射
            mapped_tz = self.timezone_mapping.get(tz_str.upper())
            if mapped_tz:
                try:
                    return pytz.timezone(mapped_tz)
                except pytz.UnknownTimeZoneError:
                    pass

        logger.warning(f"无法识别时区: {tz_str}")
        return None

    def _parse_offset_timezone(self, offset_str: str) -> timezone:
        """解析偏移量时区

        Args:
            offset_str: 偏移量字符串，如 "+08:00"

        Returns:
            timezone对象
        """
        sign = 1 if offset_str[0] == '+' else -1
        hours = int(offset_str[1:3])
        minutes = int(offset_str[4:6])

        total_minutes = sign * (hours * 60 + minutes)
        return timezone(timedelta(minutes=total_minutes))

    def convert_timezone(
        self,
        dt: datetime,
        target_tz: Union[str, timezone],
        source_tz: Optional[Union[str, timezone]] = None
    ) -> datetime:
        """转换时区

        Args:
            dt: 要转换的datetime对象
            target_tz: 目标时区
            source_tz: 源时区（如果dt没有时区信息）

        Returns:
            转换后的datetime对象
        """
        # 标准化目标时区
        target_timezone = self.normalize_timezone(target_tz)
        if target_timezone is None:
            raise TimeFormatError(f"无效的目标时区: {target_tz}")

        # 处理源时区
        if dt.tzinfo is None:
            # 如果datetime没有时区信息，需要指定源时区
            if source_tz is None:
                # 假设为本地时区
                dt = dt.replace(tzinfo=timezone.utc)
            else:
                source_timezone = self.normalize_timezone(source_tz)
                if source_timezone is None:
                    raise TimeFormatError(f"无效的源时区: {source_tz}")
                dt = dt.replace(tzinfo=source_timezone)

        # 转换时区
        if isinstance(target_timezone, pytz.BaseTzInfo):
            return dt.astimezone(target_timezone)
        else:
            return dt.astimezone(target_timezone)

    def handle_dst_transition(self, dt: datetime, tz: Union[str, timezone]) -> datetime:
        """处理夏令时转换

        Args:
            dt: datetime对象
            tz: 时区

        Returns:
            处理夏令时后的datetime对象
        """
        timezone_obj = self.normalize_timezone(tz)
        if timezone_obj is None:
            return dt

        if isinstance(timezone_obj, pytz.BaseTzInfo):
            # 使用pytz处理夏令时
            try:
                return timezone_obj.localize(dt.replace(tzinfo=None), is_dst=None)
            except pytz.AmbiguousTimeError:
                # 模糊时间，选择标准时间
                return timezone_obj.localize(dt.replace(tzinfo=None), is_dst=False)
            except pytz.NonExistentTimeError:
                # 不存在的时间，向前调整1小时
                adjusted_dt = dt + timedelta(hours=1)
                return timezone_obj.localize(adjusted_dt.replace(tzinfo=None), is_dst=True)
        else:
            # 对于固定偏移时区，直接设置
            return dt.replace(tzinfo=timezone_obj)

    def get_timezone_info(self, tz: Union[str, timezone]) -> Dict[str, Any]:
        """获取时区详细信息

        Args:
            tz: 时区

        Returns:
            时区信息字典
        """
        timezone_obj = self.normalize_timezone(tz)
        if timezone_obj is None:
            return {'error': f'无效时区: {tz}'}

        now = datetime.now(timezone_obj)

        info = {
            'timezone': str(timezone_obj),
            'current_time': now.isoformat(),
            'utc_offset': str(now.utcoffset()),
            'is_dst': bool(now.dst()) if hasattr(now, 'dst') and now.dst() is not None else False,
        }

        if isinstance(timezone_obj, pytz.BaseTzInfo):
            info.update({
                'zone_name': timezone_obj.zone,
                'dst_name': getattr(timezone_obj, '_dst_name', None),
                'std_name': getattr(timezone_obj, '_std_name', None),
            })

        return info

    def list_common_timezones(self) -> List[str]:
        """列出常见时区

        Returns:
            常见时区列表
        """
        common_zones = [
            'UTC',
            'America/New_York',
            'America/Chicago',
            'America/Denver',
            'America/Los_Angeles',
            'Europe/London',
            'Europe/Berlin',
            'Europe/Paris',
            'Asia/Shanghai',
            'Asia/Tokyo',
            'Asia/Seoul',
            'Asia/Kolkata',
            'Australia/Sydney',
        ]
        return common_zones

    def auto_detect_system_timezone(self) -> str:
        """自动检测系统时区

        Returns:
            系统时区名称
        """
        try:
            import time
            return time.tzname[0]
        except:
            return 'UTC'


class TimeRangeProcessor:
    """时间范围处理器

    处理相对时间表达式、绝对时间范围、时间边界等。
    """

    def __init__(self, timezone_handler: Optional[TimezoneHandler] = None):
        """初始化时间范围处理器

        Args:
            timezone_handler: 时区处理器
        """
        self.timezone_handler = timezone_handler or TimezoneHandler()
        self.format_parser = TimeFormatParser()

        # 相对时间模式
        self.relative_patterns = [
            (r'^(\d+)\s*(second|seconds|sec|s)?\s*ago$', 'seconds'),
            (r'^(\d+)\s*(minute|minutes|min|m)?\s*ago$', 'minutes'),
            (r'^(\d+)\s*(hour|hours|hr|h)?\s*ago$', 'hours'),
            (r'^(\d+)\s*(day|days|d)?\s*ago$', 'days'),
            (r'^(\d+)\s*(week|weeks|w)?\s*ago$', 'weeks'),
            (r'^(\d+)\s*(month|months|M)?\s*ago$', 'months'),
            (r'^(\d+)\s*(year|years|y)?\s*ago$', 'years'),
        ]

        # ES相对时间模式
        self.es_patterns = [
            (r'^now([+-]\d+[smhdwMy])(/[smhdwMy])?$', 'es_relative'),
            (r'^(\d+[smhdwMy])$', 'es_duration'),
        ]

        # 编译正则表达式
        self.compiled_relative = [(re.compile(pattern, re.IGNORECASE), unit)
                                 for pattern, unit in self.relative_patterns]
        self.compiled_es = [(re.compile(pattern), pattern_type)
                           for pattern, pattern_type in self.es_patterns]

    def parse_time_expression(self, expression: str, reference_time: Optional[datetime] = None) -> Optional[datetime]:
        """解析时间表达式

        Args:
            expression: 时间表达式
            reference_time: 参考时间（默认为当前时间）

        Returns:
            解析后的datetime对象
        """
        if reference_time is None:
            reference_time = datetime.now(timezone.utc)

        expression = expression.strip()

        # 尝试解析为绝对时间
        absolute_time = self.format_parser.parse_time(expression)
        if absolute_time:
            return absolute_time

        # 尝试解析为相对时间
        relative_time = self._parse_relative_time(expression, reference_time)
        if relative_time:
            return relative_time

        # 尝试解析为ES相对时间
        es_time = self._parse_es_relative_time(expression, reference_time)
        if es_time:
            return es_time

        logger.warning(f"无法解析时间表达式: {expression}")
        return None

    def _parse_relative_time(self, expression: str, reference_time: datetime) -> Optional[datetime]:
        """解析相对时间表达式

        Args:
            expression: 相对时间表达式
            reference_time: 参考时间

        Returns:
            计算后的datetime对象
        """
        for pattern, unit in self.compiled_relative:
            match = pattern.match(expression)
            if match:
                amount = int(match.group(1))

                if unit == 'seconds':
                    return reference_time - timedelta(seconds=amount)
                elif unit == 'minutes':
                    return reference_time - timedelta(minutes=amount)
                elif unit == 'hours':
                    return reference_time - timedelta(hours=amount)
                elif unit == 'days':
                    return reference_time - timedelta(days=amount)
                elif unit == 'weeks':
                    return reference_time - timedelta(weeks=amount)
                elif unit == 'months':
                    # 近似计算，1个月 = 30天
                    return reference_time - timedelta(days=amount * 30)
                elif unit == 'years':
                    # 近似计算，1年 = 365天
                    return reference_time - timedelta(days=amount * 365)

        return None

    def _parse_es_relative_time(self, expression: str, reference_time: datetime) -> Optional[datetime]:
        """解析ES相对时间表达式

        Args:
            expression: ES相对时间表达式
            reference_time: 参考时间

        Returns:
            计算后的datetime对象
        """
        for pattern, pattern_type in self.compiled_es:
            match = pattern.match(expression)
            if match:
                if pattern_type == 'es_relative':
                    # now-1d, now+1h 等格式
                    offset_str = match.group(1)
                    return self._apply_es_offset(reference_time, offset_str)
                elif pattern_type == 'es_duration':
                    # 1d, 2h 等格式
                    duration_str = match.group(0)
                    return self._apply_es_offset(reference_time, '-' + duration_str)

        return None

    def _apply_es_offset(self, base_time: datetime, offset_str: str) -> datetime:
        """应用ES偏移量

        Args:
            base_time: 基础时间
            offset_str: 偏移量字符串，如 "-1d", "+2h"

        Returns:
            计算后的datetime对象
        """
        # 解析偏移量
        sign = 1 if offset_str[0] == '+' else -1
        amount_str = offset_str[1:-1]
        unit = offset_str[-1]

        try:
            amount = int(amount_str) * sign
        except ValueError:
            return base_time

        # 应用偏移量
        if unit == 's':
            return base_time + timedelta(seconds=amount)
        elif unit == 'm':
            return base_time + timedelta(minutes=amount)
        elif unit == 'h':
            return base_time + timedelta(hours=amount)
        elif unit == 'd':
            return base_time + timedelta(days=amount)
        elif unit == 'w':
            return base_time + timedelta(weeks=amount)
        elif unit == 'M':
            # 月份计算
            return base_time + timedelta(days=amount * 30)
        elif unit == 'y':
            # 年份计算
            return base_time + timedelta(days=amount * 365)
        else:
            return base_time

    def parse_time_range(
        self,
        start_expr: Optional[str] = None,
        end_expr: Optional[str] = None,
        days_ago: Optional[int] = None,
        hours_ago: Optional[int] = None,
        reference_time: Optional[datetime] = None
    ) -> Tuple[Optional[datetime], Optional[datetime]]:
        """解析时间范围

        Args:
            start_expr: 开始时间表达式
            end_expr: 结束时间表达式
            days_ago: 天数前
            hours_ago: 小时前
            reference_time: 参考时间

        Returns:
            (开始时间, 结束时间) 元组
        """
        if reference_time is None:
            reference_time = datetime.now(timezone.utc)

        start_time = None
        end_time = None

        # 处理简单的相对时间参数
        if days_ago is not None:
            start_time = reference_time - timedelta(days=days_ago)
            end_time = reference_time
        elif hours_ago is not None:
            start_time = reference_time - timedelta(hours=hours_ago)
            end_time = reference_time

        # 处理时间表达式
        if start_expr:
            parsed_start = self.parse_time_expression(start_expr, reference_time)
            if parsed_start:
                start_time = parsed_start

        if end_expr:
            parsed_end = self.parse_time_expression(end_expr, reference_time)
            if parsed_end:
                end_time = parsed_end

        # 验证时间范围
        if start_time and end_time and start_time > end_time:
            logger.warning("开始时间晚于结束时间，自动交换")
            start_time, end_time = end_time, start_time

        return start_time, end_time

    def validate_time_range(
        self,
        start_time: Optional[datetime],
        end_time: Optional[datetime],
        max_range_days: Optional[int] = None
    ) -> bool:
        """验证时间范围

        Args:
            start_time: 开始时间
            end_time: 结束时间
            max_range_days: 最大范围天数

        Returns:
            是否有效
        """
        if start_time is None or end_time is None:
            return True  # 允许开放范围

        if start_time > end_time:
            return False

        if max_range_days:
            range_days = (end_time - start_time).days
            if range_days > max_range_days:
                return False

        return True

    def adjust_time_boundaries(
        self,
        start_time: Optional[datetime],
        end_time: Optional[datetime],
        precision: str = 'second',
        include_boundaries: bool = True
    ) -> Tuple[Optional[datetime], Optional[datetime]]:
        """调整时间边界

        Args:
            start_time: 开始时间
            end_time: 结束时间
            precision: 时间精度 ('second', 'minute', 'hour', 'day')
            include_boundaries: 是否包含边界

        Returns:
            调整后的(开始时间, 结束时间)
        """
        adjusted_start = start_time
        adjusted_end = end_time

        if start_time:
            if precision == 'day':
                adjusted_start = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
            elif precision == 'hour':
                adjusted_start = start_time.replace(minute=0, second=0, microsecond=0)
            elif precision == 'minute':
                adjusted_start = start_time.replace(second=0, microsecond=0)
            elif precision == 'second':
                adjusted_start = start_time.replace(microsecond=0)

        if end_time:
            if precision == 'day':
                adjusted_end = end_time.replace(hour=23, minute=59, second=59, microsecond=999999)
            elif precision == 'hour':
                adjusted_end = end_time.replace(minute=59, second=59, microsecond=999999)
            elif precision == 'minute':
                adjusted_end = end_time.replace(second=59, microsecond=999999)
            elif precision == 'second':
                adjusted_end = end_time.replace(microsecond=999999)

            if not include_boundaries:
                # 如果不包含边界，结束时间减少1微秒
                adjusted_end = adjusted_end - timedelta(microseconds=1)

        return adjusted_start, adjusted_end

    def split_time_range(
        self,
        start_time: datetime,
        end_time: datetime,
        chunk_duration: timedelta
    ) -> List[Tuple[datetime, datetime]]:
        """分割时间范围

        Args:
            start_time: 开始时间
            end_time: 结束时间
            chunk_duration: 分块持续时间

        Returns:
            时间范围分块列表
        """
        chunks = []
        current_start = start_time

        while current_start < end_time:
            current_end = min(current_start + chunk_duration, end_time)
            chunks.append((current_start, current_end))
            current_start = current_end

        return chunks

    def format_time_range_for_es(
        self,
        start_time: Optional[datetime],
        end_time: Optional[datetime],
        time_field: str = '@timestamp'
    ) -> Dict[str, Any]:
        """格式化时间范围为ES查询格式

        Args:
            start_time: 开始时间
            end_time: 结束时间
            time_field: 时间字段名

        Returns:
            ES查询字典
        """
        range_query = {}

        if start_time:
            range_query['gte'] = start_time.isoformat()

        if end_time:
            range_query['lt'] = end_time.isoformat()

        if range_query:
            return {
                'range': {
                    time_field: range_query
                }
            }
        else:
            return {'match_all': {}}


class TimeDataQualityChecker:
    """时间数据质量检查器

    检查时间数据的质量，生成质量报告，处理异常数据。
    """

    def __init__(self):
        """初始化时间数据质量检查器"""
        self.format_parser = TimeFormatParser()
        self.timezone_handler = TimezoneHandler()

        # 质量检查规则
        self.quality_rules = {
            'future_threshold_days': 30,  # 未来时间阈值（天）
            'past_threshold_years': 50,   # 过去时间阈值（年）
            'min_reasonable_year': 1970,  # 最小合理年份
            'max_reasonable_year': 2050,  # 最大合理年份
        }

    def check_time_data_quality(
        self,
        time_values: List[Any],
        field_name: str = 'timestamp'
    ) -> Dict[str, Any]:
        """检查时间数据质量

        Args:
            time_values: 时间值列表
            field_name: 字段名称

        Returns:
            质量检查报告
        """
        logger.info(f"开始检查时间数据质量: {field_name}")

        report = {
            'field_name': field_name,
            'total_count': len(time_values),
            'check_time': datetime.now(timezone.utc).isoformat(),
            'quality_score': 0.0,
            'issues': [],
            'statistics': {},
            'recommendations': []
        }

        if not time_values:
            report['issues'].append({
                'type': 'no_data',
                'severity': 'critical',
                'message': '没有时间数据',
                'count': 0
            })
            return report

        # 基础统计
        parsed_times = []
        parse_failures = []
        format_distribution = {}

        for i, value in enumerate(time_values):
            if value is None:
                parse_failures.append({
                    'index': i,
                    'value': None,
                    'reason': 'null_value'
                })
                continue

            # 检测格式
            value_str = str(value).strip()
            detected_format = self.format_parser.detect_format(value_str)

            if detected_format:
                format_distribution[detected_format] = format_distribution.get(detected_format, 0) + 1
            else:
                format_distribution['unknown'] = format_distribution.get('unknown', 0) + 1

            # 尝试解析
            parsed_time = self.format_parser.parse_time(value_str)
            if parsed_time:
                parsed_times.append({
                    'index': i,
                    'original': value,
                    'parsed': parsed_time,
                    'format': detected_format
                })
            else:
                parse_failures.append({
                    'index': i,
                    'value': value,
                    'reason': 'parse_failed'
                })

        # 更新统计信息
        report['statistics'] = {
            'parse_success_count': len(parsed_times),
            'parse_failure_count': len(parse_failures),
            'parse_success_rate': len(parsed_times) / len(time_values) if time_values else 0,
            'format_distribution': format_distribution,
            'dominant_format': max(format_distribution.items(), key=lambda x: x[1])[0] if format_distribution else None
        }

        # 质量检查
        if parsed_times:
            self._check_time_range_quality(parsed_times, report)
            self._check_format_consistency(format_distribution, report)
            self._check_time_sequence_quality(parsed_times, report)
            self._check_timezone_consistency(parsed_times, report)

        # 记录解析失败
        if parse_failures:
            report['issues'].append({
                'type': 'parse_failures',
                'severity': 'high' if len(parse_failures) > len(time_values) * 0.1 else 'medium',
                'message': f'{len(parse_failures)} 个时间值解析失败',
                'count': len(parse_failures),
                'examples': parse_failures[:5]  # 只显示前5个例子
            })

        # 计算质量分数
        report['quality_score'] = self._calculate_quality_score(report)

        # 生成建议
        report['recommendations'] = self._generate_recommendations(report)

        logger.info(f"时间数据质量检查完成，质量分数: {report['quality_score']:.2f}")
        return report

    def _check_time_range_quality(self, parsed_times: List[Dict], report: Dict[str, Any]) -> None:
        """检查时间范围质量"""
        times = [item['parsed'] for item in parsed_times]
        times.sort()

        now = datetime.now(timezone.utc)
        future_threshold = now + timedelta(days=self.quality_rules['future_threshold_days'])
        past_threshold = now - timedelta(days=self.quality_rules['past_threshold_years'] * 365)

        # 检查时间范围
        report['statistics']['time_range'] = {
            'min_time': times[0].isoformat(),
            'max_time': times[-1].isoformat(),
            'span_days': (times[-1] - times[0]).days,
            'span_years': (times[-1] - times[0]).days / 365.25
        }

        # 检查异常时间
        future_times = [t for t in times if t > future_threshold]
        past_times = [t for t in times if t < past_threshold]

        if future_times:
            report['issues'].append({
                'type': 'future_times',
                'severity': 'medium',
                'message': f'{len(future_times)} 个时间值在未来 {self.quality_rules["future_threshold_days"]} 天之后',
                'count': len(future_times),
                'examples': [t.isoformat() for t in future_times[:3]]
            })

        if past_times:
            report['issues'].append({
                'type': 'past_times',
                'severity': 'medium',
                'message': f'{len(past_times)} 个时间值在过去 {self.quality_rules["past_threshold_years"]} 年之前',
                'count': len(past_times),
                'examples': [t.isoformat() for t in past_times[:3]]
            })

        # 检查年份合理性
        unreasonable_times = [
            t for t in times
            if t.year < self.quality_rules['min_reasonable_year'] or
               t.year > self.quality_rules['max_reasonable_year']
        ]

        if unreasonable_times:
            report['issues'].append({
                'type': 'unreasonable_years',
                'severity': 'high',
                'message': f'{len(unreasonable_times)} 个时间值的年份不合理',
                'count': len(unreasonable_times),
                'examples': [t.isoformat() for t in unreasonable_times[:3]]
            })

    def _check_format_consistency(self, format_distribution: Dict[str, int], report: Dict[str, Any]) -> None:
        """检查格式一致性"""
        total_count = sum(format_distribution.values())
        format_count = len([f for f in format_distribution.keys() if f != 'unknown'])

        # 格式一致性检查
        if format_count > 1:
            # 计算主要格式的占比
            dominant_format = max(format_distribution.items(), key=lambda x: x[1])
            dominant_ratio = dominant_format[1] / total_count

            if dominant_ratio < 0.8:  # 主要格式占比低于80%
                report['issues'].append({
                    'type': 'format_inconsistency',
                    'severity': 'medium',
                    'message': f'时间格式不一致，发现 {format_count} 种格式',
                    'count': format_count,
                    'details': format_distribution
                })

        # 未知格式检查
        unknown_count = format_distribution.get('unknown', 0)
        if unknown_count > 0:
            unknown_ratio = unknown_count / total_count
            severity = 'high' if unknown_ratio > 0.1 else 'medium'

            report['issues'].append({
                'type': 'unknown_formats',
                'severity': severity,
                'message': f'{unknown_count} 个时间值格式无法识别',
                'count': unknown_count,
                'ratio': unknown_ratio
            })

    def _check_time_sequence_quality(self, parsed_times: List[Dict], report: Dict[str, Any]) -> None:
        """检查时间序列质量"""
        if len(parsed_times) < 2:
            return

        # 按索引排序（保持原始顺序）
        sorted_by_index = sorted(parsed_times, key=lambda x: x['index'])
        times = [item['parsed'] for item in sorted_by_index]

        # 检查时间序列单调性
        is_ascending = all(times[i] <= times[i+1] for i in range(len(times)-1))
        is_descending = all(times[i] >= times[i+1] for i in range(len(times)-1))

        if not (is_ascending or is_descending):
            # 计算乱序程度
            disorder_count = 0
            for i in range(len(times)-1):
                if times[i] > times[i+1]:
                    disorder_count += 1

            disorder_ratio = disorder_count / (len(times) - 1)

            if disorder_ratio > 0.1:  # 乱序比例超过10%
                report['issues'].append({
                    'type': 'time_sequence_disorder',
                    'severity': 'medium',
                    'message': f'时间序列存在乱序，乱序比例: {disorder_ratio:.2%}',
                    'count': disorder_count,
                    'ratio': disorder_ratio
                })

        # 检查时间间隔
        intervals = []
        for i in range(len(times)-1):
            interval = (times[i+1] - times[i]).total_seconds()
            intervals.append(interval)

        if intervals:
            avg_interval = sum(intervals) / len(intervals)
            max_interval = max(intervals)
            min_interval = min(intervals)

            report['statistics']['time_intervals'] = {
                'avg_seconds': avg_interval,
                'max_seconds': max_interval,
                'min_seconds': min_interval,
                'std_deviation': self._calculate_std_deviation(intervals)
            }

            # 检查异常间隔
            if max_interval > avg_interval * 10:  # 最大间隔超过平均值10倍
                report['issues'].append({
                    'type': 'large_time_gaps',
                    'severity': 'low',
                    'message': f'存在异常大的时间间隔: {max_interval:.0f} 秒',
                    'max_gap_seconds': max_interval,
                    'avg_gap_seconds': avg_interval
                })

    def _check_timezone_consistency(self, parsed_times: List[Dict], report: Dict[str, Any]) -> None:
        """检查时区一致性"""
        timezone_info = {}

        for item in parsed_times:
            dt = item['parsed']
            if dt.tzinfo:
                tz_str = str(dt.tzinfo)
                timezone_info[tz_str] = timezone_info.get(tz_str, 0) + 1
            else:
                timezone_info['naive'] = timezone_info.get('naive', 0) + 1

        if len(timezone_info) > 1:
            report['issues'].append({
                'type': 'timezone_inconsistency',
                'severity': 'medium',
                'message': f'时区不一致，发现 {len(timezone_info)} 种时区',
                'count': len(timezone_info),
                'details': timezone_info
            })

        # 检查naive datetime
        naive_count = timezone_info.get('naive', 0)
        if naive_count > 0:
            total_count = sum(timezone_info.values())
            naive_ratio = naive_count / total_count

            if naive_ratio > 0.1:  # naive时间超过10%
                report['issues'].append({
                    'type': 'naive_datetime',
                    'severity': 'medium',
                    'message': f'{naive_count} 个时间值缺少时区信息',
                    'count': naive_count,
                    'ratio': naive_ratio
                })

    def _calculate_std_deviation(self, values: List[float]) -> float:
        """计算标准差"""
        if len(values) < 2:
            return 0.0

        mean = sum(values) / len(values)
        variance = sum((x - mean) ** 2 for x in values) / (len(values) - 1)
        return variance ** 0.5

    def _calculate_quality_score(self, report: Dict[str, Any]) -> float:
        """计算质量分数 (0-100)"""
        base_score = 100.0

        # 根据问题严重程度扣分
        for issue in report['issues']:
            severity = issue['severity']
            count = issue.get('count', 0)
            total = report['total_count']

            if severity == 'critical':
                base_score -= 50.0
            elif severity == 'high':
                ratio = count / total if total > 0 else 1.0
                base_score -= min(30.0, ratio * 40.0)
            elif severity == 'medium':
                ratio = count / total if total > 0 else 1.0
                base_score -= min(20.0, ratio * 25.0)
            elif severity == 'low':
                ratio = count / total if total > 0 else 1.0
                base_score -= min(10.0, ratio * 15.0)

        # 解析成功率加分
        parse_rate = report['statistics'].get('parse_success_rate', 0)
        if parse_rate > 0.9:
            base_score += 5.0

        return max(0.0, min(100.0, base_score))

    def _generate_recommendations(self, report: Dict[str, Any]) -> List[str]:
        """生成改进建议"""
        recommendations = []

        # 基于问题类型生成建议
        issue_types = {issue['type'] for issue in report['issues']}

        if 'parse_failures' in issue_types:
            recommendations.append("建议统一时间格式，使用标准的ISO 8601格式")

        if 'format_inconsistency' in issue_types:
            recommendations.append("建议在数据写入时统一时间格式")

        if 'timezone_inconsistency' in issue_types:
            recommendations.append("建议统一使用UTC时区存储时间数据")

        if 'naive_datetime' in issue_types:
            recommendations.append("建议为所有时间数据添加时区信息")

        if 'future_times' in issue_types:
            recommendations.append("建议检查系统时钟设置和数据来源")

        if 'unreasonable_years' in issue_types:
            recommendations.append("建议添加时间范围验证规则")

        if 'time_sequence_disorder' in issue_types:
            recommendations.append("建议检查数据写入顺序和时间戳生成逻辑")

        # 质量分数建议
        quality_score = report['quality_score']
        if quality_score < 60:
            recommendations.append("数据质量较差，建议进行全面的数据清洗")
        elif quality_score < 80:
            recommendations.append("数据质量中等，建议重点解决主要问题")

        return recommendations

    def suggest_data_cleaning(self, report: Dict[str, Any]) -> Dict[str, Any]:
        """建议数据清洗方案

        Args:
            report: 质量检查报告

        Returns:
            数据清洗建议
        """
        cleaning_plan = {
            'actions': [],
            'estimated_improvement': 0.0,
            'risk_level': 'low'
        }

        for issue in report['issues']:
            issue_type = issue['type']
            severity = issue['severity']
            count = issue.get('count', 0)

            if issue_type == 'parse_failures':
                cleaning_plan['actions'].append({
                    'action': 'remove_unparseable',
                    'description': f'移除 {count} 个无法解析的时间值',
                    'impact': 'data_loss',
                    'affected_count': count
                })

            elif issue_type == 'format_inconsistency':
                cleaning_plan['actions'].append({
                    'action': 'normalize_format',
                    'description': '将所有时间值转换为统一格式',
                    'impact': 'format_change',
                    'target_format': 'iso_8601'
                })

            elif issue_type == 'timezone_inconsistency':
                cleaning_plan['actions'].append({
                    'action': 'normalize_timezone',
                    'description': '将所有时间值转换为UTC时区',
                    'impact': 'timezone_change',
                    'target_timezone': 'UTC'
                })

            elif issue_type == 'unreasonable_years':
                cleaning_plan['actions'].append({
                    'action': 'filter_unreasonable',
                    'description': f'过滤 {count} 个年份不合理的时间值',
                    'impact': 'data_loss',
                    'affected_count': count
                })

        # 估算改进效果
        total_issues = len(report['issues'])
        if total_issues > 0:
            cleaning_plan['estimated_improvement'] = min(30.0, total_issues * 5.0)

        # 评估风险级别
        data_loss_actions = [a for a in cleaning_plan['actions'] if a.get('impact') == 'data_loss']
        if data_loss_actions:
            total_loss = sum(a.get('affected_count', 0) for a in data_loss_actions)
            loss_ratio = total_loss / report['total_count'] if report['total_count'] > 0 else 0

            if loss_ratio > 0.2:
                cleaning_plan['risk_level'] = 'high'
            elif loss_ratio > 0.1:
                cleaning_plan['risk_level'] = 'medium'

        return cleaning_plan
